﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Printing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Threading;
using wpf_print.data;
using wpf_print.utils;
using wpf_print.view;
using static wpf_print.utils.PrintData;

namespace wpf_print
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        readonly PrintDialog printDialog = new();
        int PaperNum = 0; // 当前第几个分组
        int allPageNum = 0;// 共几个分组
        private List<JObject> allData = new();
        string ClickType = "http";
        BackgroundWorker bgMeet;
        Task<JObject> response;
        #region 构造函数
        public MainWindow()
        {
            InitializeComponent();
            InitConfig();
        }
        #endregion
        #region 异步
        private void BtnTestThread_Click(object sender, RoutedEventArgs e)
        {
            bgMeet = new BackgroundWorker
            {
                WorkerReportsProgress = true
            };
            bgMeet.DoWork += new DoWorkEventHandler(BgMeet_DoWork);
            bgMeet.ProgressChanged += new ProgressChangedEventHandler(BgMeet_ProgressChanged);
            bgMeet.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BgMeet_RunWorkerCompleted);

            bgMeet.RunWorkerAsync();
        }
        void BgMeet_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (ClickType == "http")
            {

                this.Dispatcher.Invoke(new Action(() =>
                {

                    ShowButton();
                    maxText.Text = allPageNum.ToString();
                    minText.Text = (PaperNum + 1).ToString();
                    print_box.Document = GetDocument(PaperNum);
                    _loading.Visibility = Visibility.Collapsed;
                    // 异步渲染完毕 提示是否直接打印
                    MessageBoxResult result = MessageBox.Show("有可打印内容是否需要打印！", "提示", MessageBoxButton.YesNo);

                    switch (result)
                    {
                        case MessageBoxResult.Yes:
                            // 开始打印
                            GlobalData.isPrint = true;
                            this.Dispatcher.Invoke(new Action(() =>
                            {
                                GlobalData.getLoadingStr = "加载中...";
                                _loading.Visibility = Visibility.Visible;
                                HideButton();
                            }));
                            ClickType = "print";
                            object s = new();
                            RoutedEventArgs es = new();
                            BtnTestThread_Click(s, es);
                            break;
                    }
                }));
            }
            else if (ClickType == "print")
            {
                ClearData();
            }
            else {
                for (var i = 0; i < allPageNum; ++i)
                {
                    Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() =>
                    {
                        DocumentViewer documentViewer = new()
                        {
                            Document = GetDocument(i)
                        };
                        printDialog.PrintDocument(documentViewer.Document.DocumentPaginator, "打印" + i);
                        pushMsg(i);
                    }));
                    if (i == allPageNum - 1) {
                        this.Dispatcher.Invoke(new Action(() =>
                        {
                            _loading.Visibility = Visibility.Collapsed;
                            ClearData();
                        }));

                    }
                }

            }


        }

        void BgMeet_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (ClickType == "http")
            {


            }
            else if (ClickType == "print")
            {
                this.Dispatcher.Invoke(new Action(() =>
                {
                    DocumentViewer documentViewer = new()
                    {
                        Document = GetDocument(e.ProgressPercentage)
                    };
                    printDialog.PrintDocument(documentViewer.Document.DocumentPaginator, "打印" + e.ProgressPercentage);
                    pushMsg(e.ProgressPercentage);
                }));

            }
            else {
            }
        }

        void BgMeet_DoWork(object sender, DoWorkEventArgs e)
        {
            this.Dispatcher.Invoke(new Action(() =>
            {
                GlobalData.getLoadingStr = "加载中...";
                _loading.Visibility = Visibility.Visible;
                HideButton();


            }));
            if (ClickType == "http")
            {

                GetData();
            }
            else if (ClickType == "print")
            {
                PrintNow();
            }
            else {


            }

        }
        #endregion
        #region 打印结束后清空
        private void ClearData() {
            this.Dispatcher.Invoke(new Action(() =>
            {
                _loading.Visibility = Visibility.Collapsed;
                //打印完毕清空
                print_box.Document = null;
                allData.Clear();
                HideButton();
                FileStream fs = new(@"c:\cache" + @"\cacheText.txt", FileMode.Create);
                StreamWriter sw = new(fs);
                sw.Write("");
                sw.Flush();
                sw.Close();
                fs.Close();
                GlobalData.isPrint = false;
                MessageBox.Show("打印完毕！");
            }));
        }
        #endregion
        #region 按钮显示隐藏
        void HideButton() {
            showDomButton.Visibility = Visibility.Collapsed;
            showDomButton1.Visibility = Visibility.Collapsed;
            showDomButton2.Visibility = Visibility.Collapsed;
            minText.Visibility = Visibility.Collapsed;
            minText.Text = "";
            showDomButton4.Visibility = Visibility.Collapsed;
            maxText.Visibility = Visibility.Collapsed;
            maxText.Text = "";


        }
        void ShowButton()
        {
            showDomButton.Visibility = Visibility.Visible;
            showDomButton1.Visibility = Visibility.Visible;
            showDomButton2.Visibility = Visibility.Visible;
            minText.Visibility = Visibility.Visible;
            showDomButton4.Visibility = Visibility.Visible;
            maxText.Visibility = Visibility.Visible;

        }
        #endregion
        #region 开始打印
        private void PrintNow()
        {
            for (var i = 0; i < allPageNum; ++i)
            {
                Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() =>
                {
                    bgMeet.ReportProgress(i);
                }));

            }

        }
        #endregion

        #region 更新打印配置
        private void PrintUpdate() {
            // 初始化 打印配置
            LocalPrintServer local = new();
            SetDefaultPrinter((string)printNameDom.SelectedValue);
            PrintQueue pq = local.GetPrintQueue((string)printNameDom.SelectedValue); //例如 local.GetPrintQueue("Microsoft XPS Document Writer"); 设置打印机
            printDialog.PrintQueue = pq;

            PrintTicket pt = pq.DefaultPrintTicket;
            pt.PageOrientation = PageOrientation.Portrait; // 纸张方向正常
            ObjectInfo pageSize = (ObjectInfo)printPage.SelectedValue;
            if (pageSize == null)
            {
                pt.PageMediaSize = new PageMediaSize(PageMediaSizeName.Unknown, 852, 1090);
            }
            else {
                pt.PageMediaSize = new PageMediaSize(PageMediaSizeName.Unknown, pageSize.Width, pageSize.Height);
            }

            printDialog.PrintTicket.Duplexing = Duplexing.OneSided;// 单侧打印
            pt.OutputQuality = OutputQuality.High; //输出高质量
            pt.PageBorderless = PageBorderless.None; // 有边打印，即设备在打印介质的边缘周围留出一定的空白不打印。
            printDialog.PrintTicket = pt;
        }
        #endregion
        #region 初始化 配置
        private void InitConfig() {
            // 初始化 打印列表
            printNameDom.ItemsSource = PrintData.GetLocalPrinters();
            printNameDom.DisplayMemberPath = "PrintName";
            printNameDom.SelectedValuePath = "PrintValue";
            printNameDom.SelectedIndex = 0;

            // 初始化 打印纸张
            printPage.ItemsSource = PrintData.GetPageData();
            printPage.DisplayMemberPath = "PrintName";
            printPage.SelectedValuePath = "PrintValue";
            printPage.SelectedIndex = 0;
        }
        #endregion

        #region 点击打印
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            GlobalData.isPrint = true;
            this.Dispatcher.Invoke(new Action(() =>
            {
                GlobalData.getLoadingStr = "加载中...";
                _loading.Visibility = Visibility.Visible;
                HideButton();
            }));
            // 打印所有分组 每个分组页数 按照i页打印
            string selectValue = (string)printNameDom.SelectedValue;
            if (
                selectValue.ToLower().Contains("PDF".ToLower()) ||
                selectValue.ToLower().Contains("Fax".ToLower()) ||
                selectValue.ToLower().Contains("XPS".ToLower()) ||
                selectValue.ToLower().Contains("OneNote".ToLower())
                 )
            {
                ClickType = "loadingPrint";

                BtnTestThread_Click(sender, e);
            }
            else {
                ClickType = "print";

                BtnTestThread_Click(sender, e);
            }
                
            
            

            

        }
        #endregion

        #region http请求 和 通知
        public void GetData()
        {
            if (File.ReadAllText("c:\\cache\\cacheText.txt") == "" || File.ReadAllText("c:\\cache\\cacheText.txt") == null)
            {
                JArray mockArray = MockData.mockArrayList;
                allData = new List<JObject>();
                foreach (var item in mockArray)
                {
                    allData.Add((JObject)item);
                }
                allPageNum = allData.Count;
            }
            else {
                JObject postedJObject = new();
                postedJObject.Add("redisKey", File.ReadAllText("c:\\cache\\cacheText.txt"));
                postedJObject.Add("isPaging", "0");
                response = HttpServe.TryPostAsync<JObject>(
                   "xxxx",
                   postedJObject
               );
                allData = new List<JObject>();
                if ((int?)response.Result?.GetValue("status") == 200)
                {
                    foreach (var item in response.Result["data"])
                    {
                        allData.Add((JObject)item);
                    }
                    allPageNum = allData.Count;

                }
                else
                {
                    allPageNum = 0;
                }
            }

            if (allData.Count == 0)
            {
                MessageBox.Show("数据获取失败！");
                _loading.Visibility = Visibility.Collapsed;
            }




        }
        public void pushMsg(int num)
        {
            var curData = allData[PaperNum];
            if ((bool)curData["isContainerData"] && (string)curData["moreData"]["containerPlace"] == "CONTAINER_PLACE_NONE")
            {
                
            }
            else
            {
                GlobalData.getLoadingStr = "正在打印第" + (num + 1) + "组数据！";
                JObject postedJObject = new();
                JObject dataObj = new();
                var pages = (JArray)curData["detailPage"]["pages"]["pages"];
                JArray curPages = new();
                for (var i = 0; i < pages.Count; ++i)
                {
                    var items = new JArray();
                    items = (JArray)pages[i]["items"];
                    JArray curItem = new JArray();
                    for (var j = 0; j < items.Count; ++j) {
                        if ((string)items[j]["number"] == "合计") {
                            continue;
                        }
                        JObject obj = new JObject();
                        obj.Add("orderItemId", items[j]["itemId"]);
                        obj.Add("id", items[j]["id"]);
                        obj.Add("skuId", items[j]["copySkuId"]);
                        obj.Add("skuName", items[j]["skuName"]);
                        obj.Add("consignmentOrderId", items[j]["consignmentOrderId"]);
                        curItem.Add(obj);
                    }
                    
                    curPages.Add(curItem);
                }
                dataObj.Add("pages", curPages);
                dataObj.Add("ackId", curData["moreData"]["ackInfo"]["ackId"]);
                dataObj.Add("regionCode", curData["moreData"]["regionCode"]);
                dataObj.Add("regionName", curData["moreData"]["regionName"]);

                var dataArr = new JArray();
                dataArr.Add(dataObj);
                postedJObject.Add("data", dataArr);

                HttpServe.TryPostAsync<JObject>(
                    "xxxx",
                    postedJObject
                );

            }
            

        }
        #endregion
        #region 打印机和纸张的选择
        private void MyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)

        {
            PrintUpdate();
        }
        private void PrintPage_SelectionChanged(object sender, SelectionChangedEventArgs e)

        {
            PrintUpdate();
        }
        #endregion
        #region 上一组和下一组
        private void Next_Page(object sender, RoutedEventArgs e)
        {
            GlobalData.getLoadingStr = "加载中...";
            _loading.Visibility = Visibility.Visible;
            var Loads = Dispatcher.BeginInvoke(DispatcherPriority.SystemIdle, new Action(() =>
            {
                if (PaperNum == (allPageNum - 1) || allPageNum == 0)
                {
                    _loading.Visibility = Visibility.Collapsed;
                    MessageBox.Show("最后一组");
                    return;
                }
                else
                {
                    _loading.Visibility = Visibility.Visible;
                    ++PaperNum;
                    minText.Text = (PaperNum + 1).ToString();
                    print_box.Document = GetDocument(PaperNum);
                }
            }));
            Loads.Completed += new EventHandler(Next_Pre_Completed);


        }
        void Next_Pre_Completed(object sender, EventArgs e)
        {
            _loading.Visibility = Visibility.Collapsed;
        }
        private void Pre_Page(object sender, RoutedEventArgs e)
        {
            GlobalData.getLoadingStr = "加载中...";
            _loading.Visibility = Visibility.Visible;
           var Loads = Dispatcher.BeginInvoke(DispatcherPriority.SystemIdle, new Action(() =>
            {
                if (PaperNum == 0 || allPageNum == 0)
                {
                    _loading.Visibility = Visibility.Collapsed;
                    MessageBox.Show("第一组");
                    return;
                }
                else
                {
                    _loading.Visibility = Visibility.Visible;
                    --PaperNum;
                    minText.Text = (PaperNum + 1).ToString();
                    print_box.Document = GetDocument(PaperNum);

                }
            }));
            Loads.Completed += new EventHandler(Next_Pre_Completed);
        }
        #endregion 上一组和下一组
        #region 获取文档
        // PaperNum 是当前第几个分组
        public FixedDocument GetDocument(int PaperNum) {
            FixedDocument fixedDoc = new();
            var area = printDialog.PrintQueue.GetPrintCapabilities(); // 获取打印
            double PagePadding = 56;
            double PageWidth = area.PageImageableArea.ExtentWidth + PagePadding * 2;
            double PageHeight = area.PageImageableArea.ExtentHeight + PagePadding * 2;
            int curPageNum;
            if (allData.Count == 0) {
                curPageNum = 0;
            } else {
                var curData = allData[PaperNum];
                if ((bool)curData["isContainerData"] && (string)curData["moreData"]["containerPlace"] == "CONTAINER_PLACE_NONE")
                {
                    curPageNum = 1;
                }
                else
                {
                    curPageNum = curData["detailPage"]["pages"]["pages"].ToString() == "" ? 0 : ((JArray)curData["detailPage"]["pages"]["pages"]).Count;

                }
                for (var i = 0; i < curPageNum; ++i)
                {
                    PageContent pageContent = new();
                    FixedPage fixedPage = new()
                    {
                        Width = PageWidth,
                        Height = PageHeight,
                        Margin = new Thickness(PagePadding)
                    };
                    bool isLast = false;
                    if (i == curPageNum - 1) {
                        isLast = true;
                    }
                    fixedPage.Children.Add(
                        InitView.GetView(curData, i, isLast)
                    );
                    ((IAddChild)pageContent).AddChild(fixedPage);
                    fixedDoc.Pages.Add(pageContent);
                }

            }
            if (curPageNum == 0) {
                PageContent pageContent = new();
                FixedPage fixedPage = new()
                {
                    Width = PageWidth,
                    Height = PageHeight,
                    Margin = new Thickness(PagePadding)
                };
                ((IAddChild)pageContent).AddChild(fixedPage);
                fixedDoc.Pages.Add(pageContent);
            }
            return fixedDoc;
        }
        #endregion
        #region 窗口变化和窗口初次加载内容渲染完毕
        void TransferFun() {
            if (this.WindowState == WindowState.Normal)
            {
                // 没打印 有数据 直接载入数据
                if (!GlobalData.isPrint)
                {
                    if (File.ReadAllText("c:\\cache\\cacheText.txt") != "" && File.ReadAllText("c:\\cache\\cacheText.txt") != null)
                    {
                        RoutedEventArgs rou = new();
                        object obj = new();
                        //无反应 只加载数据
                        ClickType = "http";
                        BtnTestThread_Click(obj, rou);
                    }
                    else {
                        MessageBoxResult result = MessageBox.Show("當前有測試數據，是否使用，僅用作測試使用", "提示", MessageBoxButton.YesNo);

                        switch (result)
                        {
                            case MessageBoxResult.Yes:
                                RoutedEventArgs rou = new();
                                object obj = new();
                                //无反应 只加载数据
                                ClickType = "http";
                                BtnTestThread_Click(obj, rou);
                                break;
                        }
                        HideButton();
                    }
                }
            }
        }
        private void Window_StateChanged(object sender, EventArgs e)
        {

            TransferFun();
        }

        private void Window_ContentRendered(object sender, EventArgs e)
        {
            TransferFun();
        }
        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            if (!GlobalData.isPrint)
            {
                e.Cancel = false;
            }
            else {
                e.Cancel = true;
                this.WindowState = WindowState.Minimized;
                /*MessageBoxResult result = MessageBox.Show("当前正在打印，是否要关闭程序?", "提示", MessageBoxButton.YesNo);

                switch (result)
                {
                    case MessageBoxResult.Yes:
                        System.Environment.Exit(0);
                        break;
                    case MessageBoxResult.No:
                        this.WindowState = WindowState.Minimized;
                        break;
                }*/

            }
          

        }
        #endregion
    }
}
